// by Xeno
private ["_direction", "_numconfv", "_newgroup", "_reta", "_vehicles", "_next_pos", "_leader", "_i", "_wp", "_endtime","_path","_road","_roads","_distance","_positions","_i_tries","_next_road"];

_pos_start = _this select 0;
_pos_end = _this select 1;
_direction = _this select 2;
_type_array = _this select 3;
_side = d_enemy_side;
if (count _this > 4) then { _side = _this select 4; };
diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"sideconvoy.sqf","Start",_this];
_crew_member = "";

d_confvdown = 0;
_numconfv = count _type_array;
_allSMVecs = [];
_leader = objNull;
_roads = _pos_start nearRoads 300;
_path = [];
_positions = [];
_i_tries = 30;
_map_center = getArray (configFile>>"CfgWorlds">>worldName >> "centerPosition");
_minimum_dist = (((_map_center select 0) max (_map_center select 1)) * 0.4);

while {_i_tries > 0 && (count _path) < 60 } do {
	_road = (_roads call XfRandomArrayVal);
	diag_log Format["(%1)[%2]: %3: %4",diag_tickTime,"sideconvoy.sqf","Trying road",getPos _road];
	_path = [getPos _road, _pos_end, ((_minimum_dist / 3) max 1000),round(_minimum_dist),90] call XfGetRoadPath;
	_i_tries = _i_tries - 1;
};
if (count _path <= 60) exitwith { true };

_road = _path select 0;
_i = 1;
while {count _positions < 12 } do {
	_next_road = _path select _i;
	_distance = (_road distance _next_road);
	if (_distance > 20) then {
		_direction = [_next_road, (_path select (_i + 1))] call XfDirTo;
		_next_pos = _next_road findEmptyPosition [0,10];
		if (count _next_pos <= 0) then { _next_pos = _next_road;};
		_positions set [count _positions, [_next_pos, _direction]];
		_road = _next_road;
	};
	_i = _i + 1;
};
diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"sideconvoy.sqf","Positions",_positions,(count _path)];

// _reta = [1,_next_pos, (_type_array select 0), _newgroup,0,_direction] call x_makevgroup;
// diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"sideconvoy.sqf","Created",_reta,(_type_array select 0)];
// _vehicles = _reta select 0;
// (_vehicles select 0) setDir _direction;
// {
	// _vec = _x;
	// _vec lock true;
	// _vec setDir _direction;
	// _vec addEventHandler ["killed", {d_confvdown = d_confvdown + 1;}];
	// [_vec,_newgroup,(getPos _vec),"REGISTER",[]] call XfMissionCreateMissionUnit;
	// {
		// [_x,_newgroup,(getPos _vec),"REGISTER",[]] call XfMissionCreateMissionUnit;
	// } foreach crew _vec;
	// _allSMVecs set [count _allSMVecs, _vec];
// } foreach _vehicles;
// if (count _allSMVecs < 0) exitWith { true };

_newgroup = [_side] call x_creategroup;
_newgroup allowFleeing 0;
_newgroup setCombatMode "GREEN";
_newgroup setFormation "NONE";
_newgroup setSpeedMode "NORMAL";
[0, _newgroup, "Convoy", "MissionFramework"] call ACV_FNCT_PutInStock;

_vehicles = nil;
for "_k" from 0 to (_numconfv - 1) do {
	_next_pos = _positions select (count _positions - (1 + _k));
	[format["vec_conv_%1",_k], (_next_pos select 0), "ICON", "ColorRed", [0.5,0.5],"",(_next_pos select 1),"mil_arrow2","",0.7] call XfCreateMarkerLocal;
	_reta = [1,(_next_pos select 0), (_type_array select _k), _newgroup,0,(_next_pos select 1)] call x_makevgroup;
	diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"sideconvoy.sqf","Created",_reta,(_type_array select _k)];
	_vehicles = _reta select 0;
	(_vehicles select 0) setDir (_next_pos select 1);
	// _next_pos = (getPos (_roads select _k)) findEmptyPosition [0, 10];
	// _next_pos set [2,0];
	// if (count _roads <= (_k + 1)) then {
		// _roads = (_next_pos nearRoads 80) call xfarraypushstack;
	// };
	// [true,[format["pos_%1",_k],_next_pos, "ELLIPSE", "ColorRed", [1,1],"",0,"","",0.7]] call XfMissionMarker;
	{
		_vec = _x;
		_vec setDir (_next_pos select 1);
		_vec addEventHandler ["killed", {d_confvdown = d_confvdown + 1;}];
		[_vec,_newgroup,(getPos _vec),"REGISTER",[]] call XfMissionCreateMissionUnit;
		{
			[_x,_newgroup,(getPos _vec),"REGISTER",[]] call XfMissionCreateMissionUnit;
		} foreach crew _vec;
		_allSMVecs set [count _allSMVecs, _vec];
	} foreach _vehicles;

	_vehicles = nil;
};

if (count _allSMVecs < 0) exitWith { true };

for [{_i = 0},{_i < count(waypoints _newgroup)},{_i = _i + 1}] do {
	deleteWaypoint [_newgroup, _i];
};

_ranks = ["COLONEL","MAJOR","CAPTAIN","LIEUTENANT","SERGEANT","CORPORAL","PRIVATE"];
for [{_i = 0},{_i < count _allSMVecs}, {_i = _i + 1}] do {
	_driver = driver (_allSMVecs select _i);
	{ _x setRank "PRIVATE";
	} foreach crew (_allSMVecs select _i);
	if (_i < count _ranks) then {
		_driver setRank (_ranks select _i);
	} else {
		_driver setRank "PRIVATE";
	};
	if (_i == 0) then {
		_newgroup selectLeader _driver;
		_leader = _driver;
	};
};

_newgroup setCombatMode "RED";
_newgroup setFormation "COLUMN";
_newgroup setSpeedMode "NORMAL";

_wp = _newgroup addWaypoint[getPos (vehicle _leader), 0];
_wp setWaypointBehaviour "SAFE";
_wp setWaypointSpeed "NORMAL";
_wp setwaypointtype "MOVE";
_wp setWaypointFormation "COLUMN";
_wp setWaypointCompletionRadius 200;
_wp setWaypointTimeout [1,1,1];

sleep 1.658;
_midway_point = false;
if (count _path > 150) then {
	_midway_point = true;
	for [{_i = 1},{_i <= 3},{_i = _i + 1}] do {
		_idx = round (((count _path) / 4) * _i);
		[format["vec_path_%1",_idx], (_path select _idx), "ICON", "ColorRed", [0.5,0.5],str(_idx),0,"hd_flag","",0.7] call XfCreateMarkerLocal;
		_wp = _newgroup addWaypoint[(_path select _idx) , 0];
		_wp setWaypointBehaviour "SAFE";
		_wp setWaypointSpeed "NORMAL";
		_wp setwaypointtype "MOVE";
		_wp setWaypointFormation "COLUMN";
		_wp setWaypointTimeout [1,1,1];
		_wp setWaypointCompletionRadius 200;
		if (_i == 1) then {
			_newgroup setCurrentWaypoint _wp;
		};
	};
};

_wp = _newgroup addWaypoint[_pos_end, 0];
_wp setWaypointBehaviour "SAFE";
_wp setWaypointSpeed "NORMAL";
_wp setwaypointtype "MOVE";
_wp setWaypointFormation "COLUMN";
_wp setWaypointTimeout [10,15,25];
_wp setWaypointCompletionRadius 200;
if (!_midway_point) then { _newgroup setCurrentWaypoint _wp; };

sleep 20.123;

private ["_convoy_close_dest","_convoy_reached_dest","_convoy_destroyed"];
_convoy_close_dest = false;
_convoy_reached_dest = false;
_convoy_destroyed = false;
_endtime = time + 3600;

_numconfv = count _allSMVecs;
_last_pos = getPos (vehicle (leader _newgroup));
_target_pos = _pos_end;
_group_footmen = grpNull;
_group_created = false;
while {DM_Mission_Chapter_CanRun AND DM_Mission_Mission_CanRun AND (!_convoy_close_dest) AND (!_convoy_destroyed)} do {
	if (X_MP) then {
		if ((call XPlayersNumber) == 0) then {
			if (!d_all_simulation_stopped) then {
				d_all_simulation_stopped = true;
				{_x enableSimulation false} forEach allUnits;
			};
		};
		waitUntil {sleep (1.012 + random 1);(call XPlayersNumber) > 0};
		if (d_all_simulation_stopped) then {
			{_x enableSimulation true} forEach allUnits;
			d_all_simulation_stopped= false;
		};
	};
	if (d_confvdown == _numconfv) exitWith {
		_convoy_destroyed = true;
	};
	if ({canMove _x} count _allSMVecs == 0) exitWith {
		_convoy_destroyed = true;
	};
	_units = units _newgroup;
	_convoy_close_dest = true;
	{
		if (!isnull _x) then {
			_vec = vehicle _x;
			if (_vec isKindof "Car") then {
				if (canMove _vec && alive _vec && (_vec distance _pos_end) > 300) then {
					_convoy_close_dest = false;
				};
			};
		};
	} foreach _allSMVecs;
	_idx = CurrentWaypoint _newgroup;
	_target_pos = waypointPosition [_newgroup, _idx];
	if ((_last_pos distance (getPos (vehicle (leader _newgroup)))) < 10) then {
		(leader _newgroup) doMove _target_pos;
	};
	{
		_distance = (driver _x) distance (leader _newgroup);
		if (_distance > 300 && ((speed _x) < 5)) then {
			(driver _x) doMove _target_pos;
			sleep 1.4367;
			(driver _x) doFollow (leader _newgroup);
		};
	} foreach _allSMVecs;
	
	{
		// We move troops which end on foot to another group.
		// This way they don't slow the convoy down.
		if ((_x isKindOf "Man") && !(_x != (vehicle _x))) then {
			if (!_group_created || isnull _group_footmen) then {
				_group_created = true;
				_group_footmen = [_side] call x_creategroup;
				_group_footmen setCombatMode "RED";
				_group_footmen setFormation "COLUMN";
				_group_footmen setSpeedMode "FULL";
				_group_footmen allowFleeing 0;
				_group_footmen setBehaviour "SAFE";
				diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"sideconvoy.sqf","Creating FootGroup",_group_footmen,(units _group_footmen)];
				[0, _group_footmen, "ConvoyFootmen", "MissionFramework"] call ACV_FNCT_PutInStock;
				
				_wp = _group_footmen addWaypoint[_pos_end, 0];
				_wp setWaypointBehaviour "SAFE";
				_wp setWaypointSpeed "FULL";
				_wp setwaypointtype "MOVE";
				_wp setWaypointFormation "COLUMN";
				_wp setWaypointTimeout [10,15,25];
				_wp setWaypointCompletionRadius 200;
				_group_footmen setCurrentWaypoint _wp;
			};
			[_x] joinSilent _group_footmen;
			diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"sideconvoy.sqf","Joining Footmen",_x,(typeof _x)];
			_x doMove _pos_end;
		} else {
			if (group _x == _group_footmen) then {
				diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"sideconvoy.sqf","Joining Vehicle",_x,(typeof _x)];
				[_x] joinSilent _newgroup;
			};
		};
	} foreach _units;
	
	_last_pos = getPos (vehicle (leader _newgroup));
	if (time > _endtime) exitWith {_convoy_reached_dest = true;};
	sleep 10.123;
};

if (_convoy_close_dest) then {
	private ["_driver","_crew","_grp","_leader"];
	_wp = _newgroup addWaypoint[_pos_end,0];
	while {DM_Mission_Chapter_CanRun AND DM_Mission_Mission_CanRun AND (!_convoy_reached_dest) AND (!_convoy_destroyed)} do {
		if (X_MP) then {
			if ((call XPlayersNumber) == 0) then {
				if (!d_all_simulation_stopped) then {
					d_all_simulation_stopped = true;
					{_x enableSimulation false} forEach allUnits;
				};
			};
			waitUntil {sleep (1.012 + random 1);(call XPlayersNumber) > 0};
			if (d_all_simulation_stopped) then {
				{_x enableSimulation true} forEach allUnits;
				d_all_simulation_stopped= false;
			};
		};
		if (d_confvdown == _numconfv) exitWith {_convoy_destroyed = true;};
		_leader = leader _newgroup;
		if (_leader distance _pos_end < 200) exitWith {_convoy_reached_dest = true;};
		if (time > _endtime) exitWith {_convoy_reached_dest = true;};
		{
			(driver _x) doMove _pos_end;
		} foreach _allSMVecs;
		sleep 5;
	};
	sleep 60;
};
_convoy_reached_dest;